﻿using System;
using System.Configuration;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace UtilZ.Dotnet.Ex.Base
{
    /// <summary>
    /// 程序集配置扩展类
    /// </summary>
    public class AssemblyConfigEx
    {
        /// <summary>
        /// 加载程序集配置,文件不存在或无效将抛出异常
        /// </summary>
        /// <param name="assembly">程序集</param>
        /// <returns>程序集配置</returns>
        public static Configuration LoadAssemblyConfig(System.Reflection.Assembly assembly)
        {
            string configFileName = assembly.Location + ".config";
            return LoadAssemblyConfig(configFileName);
        }

        /// <summary>
        /// 加载程序集配置,文件不存在或无效将抛出异常
        /// </summary>
        /// <param name="configFilePath">程序集配置文件路径</param>
        /// <returns>程序集配置</returns>
        public static Configuration LoadAssemblyConfig(string configFilePath)
        {
            if (string.IsNullOrWhiteSpace(configFilePath))
            {
                throw new ArgumentNullException(nameof(configFilePath));
            }

            if (!File.Exists(configFilePath))
            {
                throw new FileNotFoundException("程序集配置文件不存在", configFilePath);
            }

            ExeConfigurationFileMap map = new ExeConfigurationFileMap();
            map.ExeConfigFilename = configFilePath;
            Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
            return configuration;
        }

        /// <summary>
        /// 读取程序集配置中项的字符串值,获取失败或节点不存在将抛出异常
        /// </summary>
        /// <param name="configuration">Configuration</param>
        /// <param name="key">key</param>
        /// <returns>字符串值</returns>
        public static string GetValue(Configuration configuration, string key)
        {
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            if (string.IsNullOrWhiteSpace(key))
            {
                throw new ArgumentNullException(nameof(key));
            }

            KeyValueConfigurationElement ele = configuration.AppSettings.Settings[key];
            if (ele == null)
            {
                throw new ArgumentException($"配置文件\"{configuration.FilePath}\"appSettings配置项中不存在Key:\"{key}\"");
            }

            return ele.Value;
        }

        /// <summary>
        /// 读取程序集配置中项的字符串值,并转换为指定类型,获取失败或转换失败将抛出异常
        /// </summary>
        /// <typeparam name="T">目标数据类型</typeparam>
        /// <param name="configuration">Configuration</param>
        /// <param name="key">key</param>
        /// <returns>目标值</returns>
        public static T GetValue<T>(Configuration configuration, string key)
        {
            string value = GetValue(configuration, key);
            if (string.IsNullOrWhiteSpace(value))
            {
                throw new ArgumentException($"配置文件\"{configuration.FilePath}\"appSettings配置项Key:\"{key}\"值为空");
            }

            return (T)ConvertEx.ConvertToObject(typeof(T), value);
        }

        /// <summary>
        /// 读取应用程序集配置中项的字符串值,并转换为指定类型,获取失败或转换失败将抛出异常
        /// </summary>
        /// <typeparam name="T">目标数据类型</typeparam>
        /// <param name="key">key</param>
        /// <returns>目标值</returns>
        public static T GetValue<T>(string key)
        {
            if (string.IsNullOrWhiteSpace(key))
            {
                throw new ArgumentNullException(nameof(key));
            }

            string value = System.Configuration.ConfigurationManager.AppSettings[key];
            if (string.IsNullOrWhiteSpace(value))
            {
                throw new ArgumentException($"应用程序配置文件的appSettings配置项Key:\"{key}\"不存在或值为空");
            }

            return (T)ConvertEx.ConvertToObject(typeof(T), value);
        }
    }
}
